# coding=latin-1
''' Implementacion del juego Kosong
'''
import sys
sys.path.append("C:\\vs2010 workspace\\Projects\\Lib\\Lib\\Agente\\Framework")
from _utils import resultado, print_board, coord_id, cached_property, cached_indexed_property
from _base import Game

__author__ = 'Galvez - Martino - Ventura'
__version__ = '0.1'

def tablero_inicial():
    tablero = '0b0b0b00babab00c000c00C000C00BABAB00B0B0B0'
    #lista = []
    #lista.append(['0','b','0','b','0','b','0'])
    #lista.append(['0','b','a','b','a','b','0'])
    #lista.append(['0','c','0','0','0','c','0'])
    #lista.append(['0','C','0','0','0','C','0'])
    #lista.append(['0','B','A','B','A','B','0'])
    #lista.append(['0','B','0','B','0','B','0'])
    #return lista
    return tablero

class Kosong(Game):
    ''' Game component for Kosong
    '''
    
    PLAYERS = ('Minus','Mayus') 
   
    def __init__(self, board=None, enabled=0, turno=0, cacheTableros = {}, cacheHeuristic = {}):
        Game.__init__(self, *Kosong.PLAYERS)
        if board:
            self.board = board
        else:
            self.board = tablero_inicial()
        self.enabled = enabled
        self.turno = turno
        self.cacheTableros = cacheTableros
        self.cacheHeuristic = cacheHeuristic
    
    def active_player(self):
        return self.players[self.enabled]
    
    class _Move(int):
        def __str__(self):
            return coord_id(0,self)     
    
    @cached_property('__moves__')
    def moves(self):
        return self.obtenerHijosTablero(self.board, self.enabled)

    ################################## Verificar este metodo de results #########################################3
    def results(self):
        enabled_player = self.players[self.enabled]
        #if ((self.cantAMayus() < 1) or (self.cantAMinus() < 1)):
        #    print('==================================')
        #    print('a = ' + str(self.cantAMinus()))
        #    print('A = ' + str(self.cantAMayus()))
        #    printBoard(self.board)
        #    print('==================================')
        if self.turno == 50:
            r = resultado(enabled_player, self.players, self.evaluarA())
            return r
        elif(self.cantAMinus() == 0):
            if (self.enabled):
                r = resultado(enabled_player, self.players, 2)
            else:
                r = resultado(enabled_player, self.players, -2)
            return r
        elif (self.cantAMayus() == 0):
            if (self.enabled):
                r = resultado(enabled_player, self.players, -2)
            else:
                r = resultado(enabled_player, self.players, 2)
            return r
        return None        
    
    @cached_indexed_property('__next__')
    def next(self, move):
        tablero = list(self.board)
        #tablero = self.board
        filaOrigen = move[0]
        colOrigen = move[1]
        filaDestino = move[2]
        colDestino = move[3]
        pieza = tablero[(int(filaOrigen)*7)+int(colOrigen)]
        tablero[(int(filaOrigen)*7)+int(colOrigen)] = '0'
        tablero[(int(filaDestino)*7)+int(colDestino)] = pieza
        #pieza = tablero[move[0][0]*7+move[0][1]]
        #tablero[move[0][0]*7+move[0][1]] = '0'
        #tablero[move[1][0]*7+move[1][1]] = pieza
        return Kosong(''.join(tablero), (self.enabled + 1) % 2, self.turno+1, self.cacheTableros)
        #return Kosong(move, (self.enabled + 1) % 2, self.turno+1, self.cacheTableros)
    
    def __str__(self):
        return print_board(self.board, 1, len(self.board)+1)
    
    def __repr__(self):
        return '%s[%s]' % (self.players[self.enabled][0], self.board)
    
    def evaluarA(self):
        cantMayus = 0
        cantMinus = 0
        for fila in range(6):
            for col in range(7):
                if self.board[(fila*7)+col] == 'a':
                    cantMinus = cantMinus + 1
                if self.board[(fila*7)+col] == 'A':
                    cantMayus = cantMayus + 1
       
        if (self.enabled):
            return cantMinus - cantMayus
        else:
            return cantMayus - cantMinus
    
    def cantAMinus(self):
        cant = 0
        for fila in range(6):
            for col in range(7):
                if self.board[(fila*7)+col] == 'a':
                    cant = cant +1
        return cant

    def cantAMayus(self):
        cant = 0
        for fila in range(6):
            for col in range(7):
                if self.board[(fila*7)+col] == 'A':
                    cant = cant +1
        return cant
    
    def strTablero(self, tablero):
        str = ''
        for i in range(len(tablero)):
            for j in range(len(tablero[i])):
                str += tablero[i][j]
        return str
    
    def copiarTablero(self, tablero):
        nuevoTablero = []
        for i in range(len(tablero)):
            nuevoTablero.append([])
            for j in range(len(tablero[i])):
                nuevoTablero[i].append(tablero[i][j])
        self.strTablero(tablero)
        return nuevoTablero
    
    def moverA(self, tablero, fila, col, Mayus):
        listaMov = []
        indiceCol = [-1,1]
        indiceFila = [-1,1]
        for a in indiceCol:
            for b in indiceFila:
                colNueva = col + a
                filaNueva = fila + b
                if (colNueva >=0 and colNueva<=6 and filaNueva >=0 and filaNueva<=5):
                    pieza = tablero[(filaNueva*7)+colNueva]
                    if (Mayus):
                        if (pieza == '0' or pieza == 'a'or pieza == 'b'or pieza == 'c'):
                            #nuevoTablero = self.copiarTablero(tablero)
                            #nuevoTablero[i][j] = '0'
                            #nuevoTablero[i+a][j+b] = 'A'
                            #listTableros.append(nuevoTablero)
                            listaMov.append(str(fila)+str(col)+str(filaNueva)+str(colNueva))
                            #listaMov.append(((fila,col),(filaNueva,colNueva)))
                    else:
                        if (pieza == '0' or pieza == 'A'or pieza == 'B'or pieza == 'C'):
                            #nuevoTablero = self.copiarTablero(tablero)
                            #nuevoTablero[i][j] = '0'
                            #nuevoTablero[i+a][j+b] = 'a'
                            #listTableros.append(nuevoTablero)
                            listaMov.append(str(fila)+str(col)+str(filaNueva)+str(colNueva))
                            #listaMov.append(((fila,col),(filaNueva,colNueva)))
        return listaMov
    
    def moverB(self, tablero, fila, col, Mayus):
        listaMov = []
        indiceFila = [-1,1]
        indiceCol = [-1,0,1]
        for a in indiceFila:
            for b in indiceCol:
                nuevaFila = fila + a
                nuevaCol = col + b
                if (nuevaFila >=0 and nuevaFila<=5 and nuevaCol >=0 and nuevaCol<=6):
                    pieza = tablero[(nuevaFila*7)+nuevaCol]
                    if (Mayus):
                        if (pieza == '0' or pieza == 'a'or pieza == 'b'or pieza == 'c'):
                            #nuevoTablero = self.copiarTablero(tablero)
                            #nuevoTablero[i][j] = '0'
                            #nuevoTablero[i+a][j+b] = 'B'
                            #listTableros.append(nuevoTablero)
                            listaMov.append(str(fila)+str(col)+str(nuevaFila)+str(nuevaCol))
                            #listaMov.append(((fila,col),(nuevaFila,nuevaCol)))
                    else:
                        if (pieza == '0' or pieza == 'A'or pieza == 'B'or pieza == 'C'):
                            #nuevoTablero = self.copiarTablero(tablero)
                            #nuevoTablero[i][j] = '0'
                            #nuevoTablero[i+a][j+b] = 'b'
                            #listTableros.append(nuevoTablero)
                            listaMov.append(str(fila)+str(col)+str(nuevaFila)+str(nuevaCol))
                            #listaMov.append(((fila,col),(nuevaFila,nuevaCol)))
        return listaMov
    
    def moverC(self, tablero, fila, col, Mayus):
        listaMov = []
        indiceFila = [-1,1]
        indiceCol = [-1,0,1]
        for a in indiceFila:
            for b in indiceCol:
                nuevaCol = col+b
                nuevaFila = fila+a
                encontroPieza = False
                while(nuevaFila >=0 and nuevaFila<=5 and nuevaCol >=0 and nuevaCol<=6 and not encontroPieza):
                    pieza = tablero[(nuevaFila*7)+nuevaCol]
                    if (pieza != '0'):
                        encontroPieza = True
                    if (Mayus):
                        if (pieza == '0' or pieza == 'a'or pieza == 'b'or pieza == 'c'):
                             listaMov.append(str(fila)+str(col)+str(nuevaFila)+str(nuevaCol))
                             #listaMov.append(((fila,col),(nuevaFila,nuevaCol)))
                    else:
                        if (pieza == '0' or pieza == 'A'or pieza == 'B'or pieza == 'C'):
                            listaMov.append(str(fila)+str(col)+str(nuevaFila)+str(nuevaCol))
                            #listaMov.append(((fila,col),(nuevaFila,nuevaCol)))
                    nuevaCol = nuevaCol+b
                    nuevaFila = nuevaFila+a
        return listaMov
    
    def obtenerHijosTablero(self, tablero, Mayus):
        if (tablero in self.cacheTableros):
            return self.cacheTableros[tablero]
        else:
            hijos = []
            for fila in range(6):
                for col in range(7):
                    pieza = tablero[(fila*7)+col]
                    if (pieza != '0'):
                        if (pieza == 'a' and (not Mayus)):
                            hijos.extend(self.moverA(tablero, fila, col, Mayus))
                        elif (pieza == 'A' and Mayus):
                            hijos.extend(self.moverA(tablero, fila, col, Mayus))
                        elif (pieza == 'b' and (not Mayus)):
                            hijos.extend(self.moverB(tablero, fila, col, Mayus))
                        elif (pieza == 'B' and (Mayus)):
                            hijos.extend(self.moverB(tablero, fila, col, Mayus))
                        elif (pieza == 'c' and (not Mayus)):
                            hijos.extend(self.moverC(tablero, fila, col, Mayus))
                        elif (pieza == 'C' and (Mayus)):
                            hijos.extend(self.moverC(tablero, fila, col, Mayus))
            #self.cacheTableros[tablero] = hijos
            return hijos

def printBoard(tablero):
    for i in range(6):
        fila = ''
        for j in range(7):
            fila += tablero[(i*7)+j] + ' '
        print fila

if __name__ == '__main__':
    import sys
    sys.path.append("C:\\vs2010 workspace\\Projects\\Lib\\Lib\\Agente")
    from _agents import RandomAgent, FileAgent, TraceAgent
    from _base import run_match, match
    from Agente import MiniMaxObligatorio
    from time import time
    import gc
    f = open('C:/Users/Fede/Documents/Facultad/IA/Obligatorio/Lib/salida.txt', 'w')
    f.write('hola\n')
    f.close()
    printBoard(tablero_inicial())
    parametros = {'0':0, 'a':0.5, 'A':0.5, 'b':0.01, 'B':0.01, 'c':0.03, 'C':0.03}
    inicio = time()
    jugador = time()
    h = 2
    for i in range(10):
        inicio = time()
        m = match(Kosong(), MiniMaxObligatorio(name='AgenteObligatorio',horizon = h,params = parametros, heuristic = MiniMaxObligatorio.__heuristic__), RandomAgent(name='Random'))
        for move_number, moves, game_state in m:
            
            print('Mov '+str(move_number)+' '+str(game_state.players[game_state.enabled]) + ' played in ' + str(time()-jugador) + ' seconds')
            if (move_number == 50):
                print("Move 50!")  
            jugador = time()
            if move_number is None:
                fin = time()
                print(str(fin-inicio))
                print 'Result: %s' % (moves)
                print 'Final board: %r'  % (printBoard(game_state.board))
                print 'Tiempo Total: ' + str((time()-inicio)/60) + ' min.'
                print '==========Jugada' + str(1) +'============'
    
    #m = match(Kosong(), MiniMaxObligatorio(name='AgenteObligatorio',params = parametros,horizon = h, heuristic = MiniMaxObligatorio.__heuristic__), RandomAgent(name='Random'))
    #for move_number, moves, game_state in m:
    #        #print('Mov '+str(move_number)+' '+str(game_state.players[game_state.enabled]) + ' played in ' + str(time()-jugador) + ' seconds')
    #        #print ''
    #        #printBoard(game_state.board)
    #        #print ''
    #        jugador = time()
    #        if move_number is None:
    #            fin = time()
    #            print(str(fin-inicio))
    #            print 'Result: %s' % (moves)
    #            print 'Final board: %r'  % (printBoard(game_state.board))
    #            print 'Tiempo Total: ' + str((time()-inicio)/60) + ' min.'
    #            print '==========Jugada' + str(2) +'============'
    #m = match(Kosong(), MiniMaxObligatorio(name='AgenteObligatorio',params = parametros,horizon = h, heuristic = MiniMaxObligatorio.__heuristic__), RandomAgent(name='Random'))
    #for move_number, moves, game_state in m:
    #    #print('Mov '+str(move_number)+' '+str(game_state.players[game_state.enabled]) + ' played in ' + str(time()-jugador) + ' seconds')
    #    #print ''
    #    #printBoard(game_state.board)
    #    #print ''
    #    jugador = time()
    #    if move_number is None:
    #        fin = time()
    #        print(str(fin-inicio))
    #        print 'Result: %s' % (moves)
    #        print 'Final board: %r'  % (printBoard(game_state.board))
    #        print 'Tiempo Total: ' + str((time()-inicio)/60) + ' min.'
    #        print '==========Jugada' + str(3) +'============'
    print '==========FIN============'
    #run_match(Toads_Frogs(None, 0, 5, 4), RandomAgent(), FileAgent(name='Human'))         
        
